Interactive graphics with plotly
install.packages("plotly")
First Interactive Plot
library(plotly)
library(tidyverse)
p <- ggplot(data = midwest) +
geom_point(mapping = aes(x = popdensity, y = percollege))
ggplotly(p)
Customized Interactive Plot
p <- ggplot(midwest,
aes(x = popdensity, y = percollege, color = state)) +
geom_point() +
scale_x_continuous("Population Density",
breaks = seq(0, 80000, 20000)) +
scale_y_continuous("Percent College Graduates") +
scale_color_discrete("State") +
theme_bw()
ggplotly(p)
Your Turn
- Using the
starwars data, create a static ggplot and use the ggplotly function to turn it interactive.
Lord of the Rings Data
lotr <- read_tsv('https://raw.githubusercontent.com/jennybc/lotr/master/lotr_clean.tsv')
Parsed with column specification:
cols(
Film = col_character(),
Chapter = col_character(),
Character = col_character(),
Race = col_character(),
Words = col_integer()
)
lotr
Create plotly by hand
plot_ly(lotr, x = ~Words) %>% add_histogram()
Subplots
one_plot <- function(d) {
plot_ly(d, x = ~Words) %>%
add_histogram() %>%
add_annotations(
~unique(Film), x = 0.5, y = 1,
xref = "paper", yref = "paper", showarrow = FALSE
)
}
lotr %>%
split(.$Film) %>%
lapply(one_plot) %>%
subplot(nrows = 1, shareX = TRUE, titleX = FALSE) %>%
hide_legend()
Grouped bar plot
plot_ly(lotr, x = ~Race, color = ~Film) %>% add_histogram()
Plot of proportions
# number of diamonds by cut and clarity (n)
lotr_count <- count(lotr, Race, Film)
# number of diamonds by cut (nn)
lotr_prop <- left_join(lotr_count, count(lotr_count, Race, wt = n))
lotr_prop %>%
mutate(prop = n / nn) %>%
plot_ly(x = ~Race, y = ~prop, color = ~Film) %>%
add_bars() %>%
layout(barmode = "stack")
Your Turn
- Using the
gss_cat data, create a histrogram for the tvhours variable.
- Using the
gss_cat data, create a bar chart showing the partyid variable by the marital status.
Scatterplots by Hand
plot_ly(midwest, x = ~popdensity, y = ~percollege) %>%
add_markers()
Change symbol
plot_ly(midwest, x = ~popdensity, y = ~percollege) %>%
add_markers(symbol = ~state)
Change color
plot_ly(midwest, x = ~popdensity, y = ~percollege) %>%
add_markers(color = ~state, colors = viridis::viridis(5))
Line Graph
storms_yearly <- storms %>%
group_by(year) %>%
summarise(num = length(unique(name)))
plot_ly(storms_yearly, x = ~year, y = ~num) %>%
add_lines()
Highcharter; Highcharts for R
devtools::install_github("jbkunst/highcharter")
hchart function
library(highcharter)
Highcharts (www.highcharts.com) is a Highsoft software product which is
not free for commercial and Governmental use
lotr_count <- lotr %>%
count(Film, Race)
hchart(lotr_count, "column", hcaes(x = Race, y = n, group = Film))
A second hchart
hchart(midwest, "scatter", hcaes(x = popdensity, y = percollege, group = state))
Histogram
hchart(lotr$Words)
Build Highcharts from scratch
hc <- highchart() %>%
hc_xAxis(categories = lotr_count$Race) %>%
hc_add_series(name = 'The Fellowship Of The Ring',
data = filter(lotr_count, Film == 'The Fellowship Of The Ring')$n) %>%
hc_add_series(name = 'The Two Towers',
data = filter(lotr_count, Film == 'The Two Towers')$n) %>%
hc_add_series(name = 'The Return Of The King',
data = filter(lotr_count, Film == 'The Return Of The King')$n)
hc
Change Chart type
hc <- hc %>%
hc_chart(type = 'column')
hc
Change Colors
hc <- hc %>%
hc_colors(substr(viridis(3), 0, 7))
hc
Modify Axes
hc <- hc %>%
hc_xAxis(title = list(text = "Race")) %>%
hc_yAxis(title = list(text = "Number of Words Spoken"),
showLastLabel = FALSE)
hc
Add title, subtitle, move legend
hc <- hc %>%
hc_title(text = 'Number of Words Spoken in Lord of the Rings Films',
align = 'left') %>%
hc_subtitle(text = 'Broken down by <i>Film</i> and <b>Race</b>',
align = 'left') %>%
hc_legend(align = 'right', verticalAlign = 'top', layout = 'vertical',
x = 0, y = 80) %>%
hc_exporting(enabled = TRUE)
hc
Correlation Matrices
select(storms, wind, pressure, ts_diameter, hu_diameter) %>%
cor(use = "pairwise.complete.obs") %>%
hchart()
Leaflet Example
library(leaflet)
storms %>%
filter(name %in% c('Ike', 'Katrina'), year > 2000) %>%
leaflet() %>%
addTiles() %>%
addCircles(lng = ~long, lat = ~lat, popup = ~name, weight = 1,
radius = ~wind*1000)
LS0tDQp0aXRsZTogIkRhdGEgVmlzdWFsaXphdGlvbiAtIEludGVyYWN0aXZlIEdyYXBoaWNzIHVzaW5nIFIiDQphdXRob3I6ICJCcmFuZG9uIExlQmVhdSINCmRhdGU6ICJKdW5lIDUsIDIwMTgiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBzZXR1cF9jaHVua3MsIGVjaG8gPSBGQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9NiwgZmlnLmNhcCA9IE5VTEwpIA0KYGBgDQoNCiMgSW50ZXJhY3RpdmUgZ3JhcGhpY3Mgd2l0aCBwbG90bHkNCmBgYHtyIGluc3RhbGwsIGV2YWwgPSBGQUxTRX0NCmluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQpgYGANCg0KIyBGaXJzdCBJbnRlcmFjdGl2ZSBQbG90DQpgYGB7ciBmaXJzdF9wbG90bHksIG1lc3NhZ2UgPSBGQUxTRSwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDZ9DQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KcCA8LSBnZ3Bsb3QoZGF0YSA9IG1pZHdlc3QpICsNCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBwb3BkZW5zaXR5LCB5ID0gcGVyY29sbGVnZSkpDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCiMgQ3VzdG9taXplZCBJbnRlcmFjdGl2ZSBQbG90DQpgYGB7ciBjdXN0b21fcGxvdGx5LCB3YXJuaW5nID0gRkFMU0UsIGZpZy53aWR0aCA9IDksIGZpZy5oZWlnaHQgPSA2fQ0KcCA8LSBnZ3Bsb3QobWlkd2VzdCwgDQogICAgICAgYWVzKHggPSBwb3BkZW5zaXR5LCB5ID0gcGVyY29sbGVnZSwgY29sb3IgPSBzdGF0ZSkpICsNCiAgZ2VvbV9wb2ludCgpICsgDQogIHNjYWxlX3hfY29udGludW91cygiUG9wdWxhdGlvbiBEZW5zaXR5IiwgDQogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgODAwMDAsIDIwMDAwKSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKCJQZXJjZW50IENvbGxlZ2UgR3JhZHVhdGVzIikgKyANCiAgc2NhbGVfY29sb3JfZGlzY3JldGUoIlN0YXRlIikgKyANCiAgdGhlbWVfYncoKQ0KZ2dwbG90bHkocCkNCmBgYA0KDQojIFlvdXIgVHVybg0KMS4gVXNpbmcgdGhlIGBzdGFyd2Fyc2AgZGF0YSwgY3JlYXRlIGEgc3RhdGljIGdncGxvdCBhbmQgdXNlIHRoZSBgZ2dwbG90bHlgIGZ1bmN0aW9uIHRvIHR1cm4gaXQgaW50ZXJhY3RpdmUuIA0KMi4gDQoNCiMgTG9yZCBvZiB0aGUgUmluZ3MgRGF0YQ0KLSBEYXRhIGZyb20gSmVubnkgQnJ5YW46IDxodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9sb3RyPg0KDQpgYGB7ciByZWFkX2luX2xvdHIsIGVycm9yID0gRkFMU0V9DQpsb3RyIDwtIHJlYWRfdHN2KCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vamVubnliYy9sb3RyL21hc3Rlci9sb3RyX2NsZWFuLnRzdicpDQpsb3RyDQpgYGANCg0KIyBDcmVhdGUgcGxvdGx5IGJ5IGhhbmQNCmBgYHtyIHBsb3RseV9ieV9oYW5kLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gNn0NCnBsb3RfbHkobG90ciwgeCA9IH5Xb3JkcykgJT4lIGFkZF9oaXN0b2dyYW0oKQ0KYGBgDQoNCiMgU3VicGxvdHMNCmBgYHtyIHN1YnBsb3RzLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gNn0NCm9uZV9wbG90IDwtIGZ1bmN0aW9uKGQpIHsNCiAgcGxvdF9seShkLCB4ID0gfldvcmRzKSAlPiUNCiAgICBhZGRfaGlzdG9ncmFtKCkgJT4lDQogICAgYWRkX2Fubm90YXRpb25zKA0KICAgICAgfnVuaXF1ZShGaWxtKSwgeCA9IDAuNSwgeSA9IDEsIA0KICAgICAgeHJlZiA9ICJwYXBlciIsIHlyZWYgPSAicGFwZXIiLCBzaG93YXJyb3cgPSBGQUxTRQ0KICAgICkNCn0NCg0KbG90ciAlPiUNCiAgc3BsaXQoLiRGaWxtKSAlPiUNCiAgbGFwcGx5KG9uZV9wbG90KSAlPiUgDQogIHN1YnBsb3QobnJvd3MgPSAxLCBzaGFyZVggPSBUUlVFLCB0aXRsZVggPSBGQUxTRSkgJT4lDQogIGhpZGVfbGVnZW5kKCkNCmBgYA0KDQoNCiMgR3JvdXBlZCBiYXIgcGxvdA0KYGBge3IgcGxvdGx5X2dyb3VwLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gNn0NCnBsb3RfbHkobG90ciwgeCA9IH5SYWNlLCBjb2xvciA9IH5GaWxtKSAlPiUgYWRkX2hpc3RvZ3JhbSgpDQpgYGANCg0KIyBQbG90IG9mIHByb3BvcnRpb25zDQpgYGB7ciBwbG90bHlfcHJvcG9ydGlvbnMsIG1lc3NhZ2UgPSBGQUxTRSwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDZ9DQojIG51bWJlciBvZiBkaWFtb25kcyBieSBjdXQgYW5kIGNsYXJpdHkgKG4pDQpsb3RyX2NvdW50IDwtIGNvdW50KGxvdHIsIFJhY2UsIEZpbG0pDQojIG51bWJlciBvZiBkaWFtb25kcyBieSBjdXQgKG5uKQ0KbG90cl9wcm9wIDwtIGxlZnRfam9pbihsb3RyX2NvdW50LCBjb3VudChsb3RyX2NvdW50LCBSYWNlLCB3dCA9IG4pKQ0KbG90cl9wcm9wICU+JQ0KICBtdXRhdGUocHJvcCA9IG4gLyBubikgJT4lDQogIHBsb3RfbHkoeCA9IH5SYWNlLCB5ID0gfnByb3AsIGNvbG9yID0gfkZpbG0pICU+JQ0KICBhZGRfYmFycygpICU+JQ0KICBsYXlvdXQoYmFybW9kZSA9ICJzdGFjayIpDQpgYGANCg0KIyBZb3VyIFR1cm4NCjEuIFVzaW5nIHRoZSBgZ3NzX2NhdGAgZGF0YSwgY3JlYXRlIGEgaGlzdHJvZ3JhbSBmb3IgdGhlIGB0dmhvdXJzYCB2YXJpYWJsZS4gDQoyLiBVc2luZyB0aGUgYGdzc19jYXRgIGRhdGEsIGNyZWF0ZSBhIGJhciBjaGFydCBzaG93aW5nIHRoZSBgcGFydHlpZGAgdmFyaWFibGUgYnkgdGhlIGBtYXJpdGFsYCBzdGF0dXMuDQoNCiMgU2NhdHRlcnBsb3RzIGJ5IEhhbmQNCmBgYHtyIHBsb3RseV9zY2F0dGVyLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gNiwgd2FybmluZyA9IEZBTFNFfQ0KcGxvdF9seShtaWR3ZXN0LCB4ID0gfnBvcGRlbnNpdHksIHkgPSB+cGVyY29sbGVnZSkgJT4lDQogIGFkZF9tYXJrZXJzKCkNCmBgYA0KDQojIENoYW5nZSBzeW1ib2wNCmBgYHtyIHBsb3RseV9zeW1ib2wsIGZpZy53aWR0aCA9IDksIGZpZy5oZWlnaHQgPSA2fQ0KcGxvdF9seShtaWR3ZXN0LCB4ID0gfnBvcGRlbnNpdHksIHkgPSB+cGVyY29sbGVnZSkgJT4lDQogIGFkZF9tYXJrZXJzKHN5bWJvbCA9IH5zdGF0ZSkNCmBgYA0KDQojIENoYW5nZSBjb2xvcg0KYGBge3IgcGxvdGx5X2NvbG9yLCBmaWcuaGVpZ2h0ID0gNiwgZmlnLndpZHRoID0gOX0NCnBsb3RfbHkobWlkd2VzdCwgeCA9IH5wb3BkZW5zaXR5LCB5ID0gfnBlcmNvbGxlZ2UpICU+JQ0KICBhZGRfbWFya2Vycyhjb2xvciA9IH5zdGF0ZSwgY29sb3JzID0gdmlyaWRpczo6dmlyaWRpcyg1KSkNCmBgYA0KDQojIExpbmUgR3JhcGgNCmBgYHtyIHBsb3RseV9saW5lLCBmaWcuaGVpZ2h0ID0gNiwgZmlnLndpZHRoID0gOX0NCnN0b3Jtc195ZWFybHkgPC0gc3Rvcm1zICU+JQ0KICBncm91cF9ieSh5ZWFyKSAlPiUNCiAgc3VtbWFyaXNlKG51bSA9IGxlbmd0aCh1bmlxdWUobmFtZSkpKQ0KDQpwbG90X2x5KHN0b3Jtc195ZWFybHksIHggPSB+eWVhciwgeSA9IH5udW0pICU+JQ0KICBhZGRfbGluZXMoKQ0KYGBgDQoNCiMgWW91ciBUdXJuDQoxLiANCjIuIA0KDQojIEhpZ2hjaGFydGVyOyBIaWdoY2hhcnRzIGZvciBSDQpgYGB7ciBpbnN0YWxsX2hpZ2hjaGFydGVyLCBldmFsID0gRkFMU0V9DQpkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImpia3Vuc3QvaGlnaGNoYXJ0ZXIiKQ0KYGBgDQoNCiMgYGhjaGFydGAgZnVuY3Rpb24NCmBgYHtyIGhjaGFydDEsIGZpZy5oZWlnaHQgPSA2LCBmaWcud2lkdGggPSA5fQ0KbGlicmFyeShoaWdoY2hhcnRlcikNCg0KbG90cl9jb3VudCA8LSBsb3RyICU+JQ0KICBjb3VudChGaWxtLCBSYWNlKQ0KDQpoY2hhcnQobG90cl9jb3VudCwgImNvbHVtbiIsIGhjYWVzKHggPSBSYWNlLCB5ID0gbiwgZ3JvdXAgPSBGaWxtKSkNCmBgYA0KDQojIEEgc2Vjb25kIGBoY2hhcnRgDQpgYGB7ciBoY2hhcnQyLCBmaWcuaGVpZ2h0ID0gNiwgZmlnLndpZHRoID0gOX0NCmhjaGFydChtaWR3ZXN0LCAic2NhdHRlciIsIGhjYWVzKHggPSBwb3BkZW5zaXR5LCB5ID0gcGVyY29sbGVnZSwgZ3JvdXAgPSBzdGF0ZSkpDQpgYGANCg0KIyBIaXN0b2dyYW0NCmBgYHtyIGhjaGFydF9oaXN0LCBmaWcuaGVpZ2h0ID0gNiwgZmlnLndpZHRoID0gOX0NCmhjaGFydChsb3RyJFdvcmRzKQ0KYGBgDQoNCiMgWW91ciBUdXJuDQoxLiANCjIuIA0KDQojIEJ1aWxkIEhpZ2hjaGFydHMgZnJvbSBzY3JhdGNoDQpgYGB7ciBoY19zY3JhdGNoLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gNn0NCmhjIDwtIGhpZ2hjaGFydCgpICU+JQ0KICBoY194QXhpcyhjYXRlZ29yaWVzID0gbG90cl9jb3VudCRSYWNlKSAlPiUNCiAgaGNfYWRkX3NlcmllcyhuYW1lID0gJ1RoZSBGZWxsb3dzaGlwIE9mIFRoZSBSaW5nJywgDQogICAgICAgICAgICAgICAgZGF0YSA9IGZpbHRlcihsb3RyX2NvdW50LCBGaWxtID09ICdUaGUgRmVsbG93c2hpcCBPZiBUaGUgUmluZycpJG4pICU+JSANCiAgaGNfYWRkX3NlcmllcyhuYW1lID0gJ1RoZSBUd28gVG93ZXJzJywgDQogICAgICAgICAgICAgICAgZGF0YSA9IGZpbHRlcihsb3RyX2NvdW50LCBGaWxtID09ICdUaGUgVHdvIFRvd2VycycpJG4pICU+JQ0KICBoY19hZGRfc2VyaWVzKG5hbWUgPSAnVGhlIFJldHVybiBPZiBUaGUgS2luZycsIA0KICAgICAgICAgICAgICAgIGRhdGEgPSBmaWx0ZXIobG90cl9jb3VudCwgRmlsbSA9PSAnVGhlIFJldHVybiBPZiBUaGUgS2luZycpJG4pDQpoYw0KYGBgDQoNCiMgQ2hhbmdlIENoYXJ0IHR5cGUNCmBgYHtyIGhjX2NoYXJ0LCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gNn0NCmhjIDwtIGhjICU+JQ0KICBoY19jaGFydCh0eXBlID0gJ2NvbHVtbicpDQpoYw0KYGBgDQoNCiMgQ2hhbmdlIENvbG9ycw0KYGBge3IgaGNfY2hhbmdlX2NvbG9ycywgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDZ9DQpoYyA8LSBoYyAlPiUNCiAgaGNfY29sb3JzKHN1YnN0cih2aXJpZGlzKDMpLCAwLCA3KSkNCmhjDQpgYGANCg0KIyBNb2RpZnkgQXhlcw0KYGBge3IgaGNfYXhpcywgZmlnLmhlaWdodCA9IDYsIGZpZy53aWR0aCA9IDl9DQpoYyA8LSBoYyAlPiUNCiAgaGNfeEF4aXModGl0bGUgPSBsaXN0KHRleHQgPSAiUmFjZSIpKSAlPiUNCiAgaGNfeUF4aXModGl0bGUgPSBsaXN0KHRleHQgPSAiTnVtYmVyIG9mIFdvcmRzIFNwb2tlbiIpLA0KICAgICAgICAgICBzaG93TGFzdExhYmVsID0gRkFMU0UpDQpoYw0KYGBgDQoNCiMgQWRkIHRpdGxlLCBzdWJ0aXRsZSwgbW92ZSBsZWdlbmQNCmBgYHtyIGhjX21vZGlmeSwgZmlnLmhlaWdodCA9IDYsIGZpZy53aWR0aCA9IDl9DQpoYyA8LSBoYyAlPiUNCiAgaGNfdGl0bGUodGV4dCA9ICdOdW1iZXIgb2YgV29yZHMgU3Bva2VuIGluIExvcmQgb2YgdGhlIFJpbmdzIEZpbG1zJywNCiAgICAgICAgICAgYWxpZ24gPSAnbGVmdCcpICU+JQ0KICBoY19zdWJ0aXRsZSh0ZXh0ID0gJ0Jyb2tlbiBkb3duIGJ5IDxpPkZpbG08L2k+IGFuZCA8Yj5SYWNlPC9iPicsIA0KICAgICAgICAgICAgICBhbGlnbiA9ICdsZWZ0JykgJT4lDQogIGhjX2xlZ2VuZChhbGlnbiA9ICdyaWdodCcsIHZlcnRpY2FsQWxpZ24gPSAndG9wJywgbGF5b3V0ID0gJ3ZlcnRpY2FsJywNCiAgICAgICAgICAgIHggPSAwLCB5ID0gODApICU+JQ0KICBoY19leHBvcnRpbmcoZW5hYmxlZCA9IFRSVUUpDQpoYw0KYGBgDQoNCg0KIyBZb3VyIFR1cm4NCjEuIA0KMi4gDQoNCiMgQ29ycmVsYXRpb24gTWF0cmljZXMNCmBgYHtyIGNvcnJlbGF0aW9ufQ0Kc2VsZWN0KHN0b3Jtcywgd2luZCwgcHJlc3N1cmUsIHRzX2RpYW1ldGVyLCBodV9kaWFtZXRlcikgJT4lDQogIGNvcih1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIikgJT4lDQogIGhjaGFydCgpDQpgYGANCg0KIyBMZWFmbGV0IEV4YW1wbGUNCmBgYHtyIGxlYWZsZXR9DQpsaWJyYXJ5KGxlYWZsZXQpDQoNCnN0b3JtcyAlPiUNCiAgZmlsdGVyKG5hbWUgJWluJSBjKCdJa2UnLCAnS2F0cmluYScpLCB5ZWFyID4gMjAwMCkgJT4lDQogIGxlYWZsZXQoKSAlPiUNCiAgYWRkVGlsZXMoKSAlPiUNCiAgYWRkQ2lyY2xlcyhsbmcgPSB+bG9uZywgbGF0ID0gfmxhdCwgcG9wdXAgPSB+bmFtZSwgd2VpZ2h0ID0gMSwNCiAgICAgICAgICAgICByYWRpdXMgPSB+d2luZCoxMDAwKQ0KYGBgDQoNCg0KIyBBZGRpdGlvbmFsIFJlc291cmNlcw0KKiBwbG90bHkgZm9yIFIgYm9vazogPGh0dHBzOi8vcGxvdGx5LWJvb2suY3BzaWV2ZXJ0Lm1lLz4NCiogcGxvdGx5OiA8aHR0cHM6Ly9wbG90Lmx5Lz4NCiogaGlnaGNoYXJ0ZXI6IDxodHRwOi8vamt1bnN0LmNvbS9oaWdoY2hhcnRlci9pbmRleC5odG1sPg0KKiBoaWdoY2hhcnRzOiA8aHR0cHM6Ly93d3cuaGlnaGNoYXJ0cy5jb20vPg0KKiBodG1sd2lkZ2V0czogPGh0dHBzOi8vd3d3Lmh0bWx3aWRnZXRzLm9yZy8+DQo=